#include "thread.h"
#include "log.h"
#include "util.h"

#include<errno.h>

namespace sylar
{

static thread_local Thread* t_thread = nullptr;
static thread_local std::string t_thread_name = "UNKNOW_thraed_name";

static sylar::Logger::LoggerPtr g_logger = SYLAR_LOG_NAME("system");

Thread* Thread::GetThis()
{
    return t_thread;
}

const std::string& Thread::GetName()
{
    return t_thread_name;
}

void Thread::SetName(const std::string& name)
{
    if (t_thread)
    {
        t_thread->m_name = name;
    }
    t_thread_name = name;
}



Semaphore::Semaphore(uint32_t count)
{
    if (sem_init(&m_semaphore, 0, count))
    {
        throw std::logic_error("sem init error");
    }
}
Semaphore::~Semaphore()
{
    sem_destroy(&m_semaphore);
}

void Semaphore::wait()
{
    if (sem_wait(&m_semaphore))
    {
        throw std::logic_error("sem_wait error");
    }
    
}
void Semaphore::notify()
{
    if (sem_post(&m_semaphore))
    {
        throw std::logic_error("sem_post error");
    }
}


Thread::Thread(std::function<void()> cb, const std::string& name)
    : m_cb(cb)
    , m_name(name)
{
    if (name.empty())
    {
        m_name = "UNKUNOW";
    }
    int iRet = pthread_create(&m_thread, nullptr, &Thread::run, this);
    if (iRet)
    {
        SYLAR_LOG_ERROR(g_logger) << "pthread create error return" << iRet
        << " name= " << m_name;
        throw std::logic_error("pthread create error");
    }
   // m_semaphore.wait(); // 等待线程运行起来
}

Thread::~Thread()
{
    if (m_thread)
    {
        pthread_detach(m_thread);
    }
}

void Thread::join()
{
    if (m_thread)
    {
       int iRet = pthread_join(m_thread, NULL);
       if (iRet)
       {
            SYLAR_LOG_ERROR(g_logger) << "pthread join error return" << iRet
            << " name= " << m_name;
            throw std::logic_error("pthread join error");
       }
       m_thread = 0;
    }
}

void* Thread::run(void* arg)
{
    Thread* thread = (Thread*)arg;
    t_thread = thread;
    t_thread_name = thread->m_name;
    thread->m_id = GetThreadId();
    pthread_setname_np(pthread_self(), thread->m_name.substr(0,15).c_str());  
    std::function<void(void)> cb;
    cb.swap(thread->m_cb);

    //thread->m_semaphore.notify(); 
    cb();
    return nullptr;
}
    
}